home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / mpeg / main.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  13KB  |  620 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  * 
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  * 
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. #include "video.h"
  22. #include "proto.h"
  23. #include <sys/types.h>
  24. #include <signal.h>
  25. #ifndef MIPS
  26. #include <netinet/in.h>
  27. #else
  28. #include <bsd/netinet/in.h>
  29. #endif
  30.  
  31. #include "util.h"
  32. #include "dither.h"
  33.  
  34. /* Define buffer length. */
  35.  
  36. #define BUF_LENGTH 80000
  37.  
  38. /* Function return type declarations */
  39. void usage();
  40.  
  41. /* External declaration of main decoding call. */
  42.  
  43. extern VidStream *mpegVidRsrc();
  44. extern VidStream *NewVidStream();
  45.  
  46. /* Declaration of global variable to hold dither info. */
  47.  
  48. int ditherType;
  49.  
  50. /* Global file pointer to incoming data. */
  51. FILE *input;
  52.  
  53. /* End of File flag. */
  54. static int EOF_flag = 0;
  55.  
  56. /* Loop flag. */
  57. int loopFlag = 0;
  58.  
  59. /* Shared memory flag. */
  60. int shmemFlag = 0;
  61.  
  62. /* Quiet flag. */
  63. int quietFlag = 0;
  64.  
  65. /* Display image on screen? */
  66. int noDisplayFlag = 0;
  67.  
  68. /* Setjmp/Longjmp env. */
  69. jmp_buf env;
  70.  
  71.  
  72. /*
  73.  *--------------------------------------------------------------
  74.  *
  75.  * get_more_data --
  76.  *
  77.  *    Called by correct_underflow in bit parsing utilities to
  78.  *      read in more data.
  79.  *
  80.  * Results:
  81.  *    Input buffer updated, buffer length updated.
  82.  *      Returns 1 if data read, 0 if EOF, -1 if error.
  83.  *
  84.  * Side effects:
  85.  *      None.
  86.  *
  87.  *--------------------------------------------------------------
  88.  */
  89.  
  90. int 
  91. get_more_data(buf_start, max_length, length_ptr, buf_ptr)
  92.      unsigned int *buf_start;
  93.      int max_length;
  94.      int *length_ptr;
  95.      unsigned int **buf_ptr;
  96. {
  97.   
  98.   int length, num_read, i, request;
  99.   unsigned char *buffer, *mark;
  100.   unsigned int *lmark;
  101.  
  102.   if (EOF_flag) return 0;
  103.  
  104.   length = *length_ptr;
  105.   buffer = (unsigned char *) *buf_ptr;
  106.  
  107.   if (length > 0) {
  108.     memcpy((unsigned char *) buf_start, buffer, (length*4));
  109.     mark = ((unsigned char *) (buf_start + length));
  110.   }
  111.   else {
  112.     mark = (unsigned char *) buf_start;
  113.     length = 0;
  114.   }
  115.  
  116.   request = (max_length-length)*4;
  117.   
  118.   num_read = fread( mark, 1, request, input);
  119.  
  120.   /* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
  121.   {
  122.     int num_read_rounded;
  123.     unsigned char *index;
  124.  
  125.     num_read_rounded = 4*(num_read/4);
  126.  
  127.     /* this can happen only if num_read<request; i.e. end of file reached */
  128.     if( num_read_rounded < num_read )
  129.       { 
  130.      num_read_rounded = 4*( num_read/4+1 );
  131.      /* fill in with zeros */
  132.      for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
  133.      /* advance to the next 4-byte boundary */
  134.      num_read = num_read_rounded;
  135.       }
  136.   }
  137.   
  138.   if   (num_read < 0) {
  139.     return -1;
  140.   }
  141.   else if (num_read == 0) {
  142.     *buf_ptr = buf_start;
  143.     
  144.     /* Make 32 bits after end equal to 0 and 32
  145.        bits after that equal to seq end code
  146.        in order to prevent messy data from infinite
  147.        recursion.
  148.     */
  149.  
  150.     *(buf_start + length) = 0x0;
  151.     *(buf_start + length+1) = SEQ_END_CODE;
  152.  
  153.     EOF_flag = 1;
  154.     return 0;
  155.   }
  156.  
  157.   lmark = (unsigned int *) mark;
  158.  
  159.   num_read = num_read/4;
  160.  
  161.   for (i=0; i<num_read; i++) {
  162.     *lmark = htonl(*lmark);
  163.     lmark++;
  164.   }
  165.  
  166.   *buf_ptr = buf_start;
  167.   *length_ptr = length + num_read;
  168.  
  169.   return 1;
  170. }
  171.  
  172. /*
  173.  *--------------------------------------------------------------
  174.  *
  175.  * int_handler --
  176.  *
  177.  *    Handles Cntl-C interupts..
  178.  *
  179.  * Results:
  180.  *    None.
  181.  *
  182.  * Side effects:
  183.  *    None.
  184.  *
  185.  *--------------------------------------------------------------
  186.  */
  187. void
  188. int_handler()
  189. {
  190.   if (!quietFlag) {
  191.     fprintf(stderr, "Interrupted!\n");
  192.   }
  193.   if (curVidStream != NULL)
  194.     DestroyVidStream(curVidStream);
  195.   exit(1);
  196. }
  197.  
  198.  
  199. /*
  200.  *--------------------------------------------------------------
  201.  *
  202.  * main --
  203.  *
  204.  *    Parses command line, starts decoding and displaying.
  205.  *
  206.  * Results:
  207.  *    None.
  208.  *
  209.  * Side effects:
  210.  *    None.
  211.  *
  212.  *--------------------------------------------------------------
  213.  */
  214.  
  215. void
  216. main(argc, argv)
  217.      int argc;
  218.      char **argv;
  219. {
  220.  
  221.   char *name;
  222.   static VidStream *theStream;
  223.   int mark;
  224.   int i;
  225.  
  226.   mark = 1;
  227.   argc--;
  228.  
  229.   name = "";
  230.   input = stdin;
  231.   ditherType = ORDERED2_DITHER;
  232.   LUM_RANGE = 8;
  233.   CR_RANGE = CB_RANGE = 4;
  234.   noDisplayFlag = 0;
  235.  
  236. #ifdef SH_MEM
  237.   shmemFlag = 1;
  238. #endif
  239.  
  240.   while (argc) {
  241.     if (strcmp(argv[mark], "-nop") == 0) {
  242.       TogglePFlag();
  243.       argc--; mark++;
  244.     } else if (strcmp(argv[mark], "-nob") == 0) {
  245.       ToggleBFlag();
  246.       argc--; mark++;
  247.     } else if (strcmp(argv[mark], "-display") == 0) {
  248.       name = argv[++mark];
  249.       argc -= 2; mark++;
  250.     } else if (strcmp(argv[mark], "-dither") == 0) {
  251.       argc--; mark++;
  252.       if (argc < 1) {
  253.     perror("Must specify dither option after -dither flag");
  254.     usage(argv[0]);
  255.       }
  256.       if (strcmp(argv[mark], "hybrid") == 0) {
  257.     argc--; mark++;
  258.     ditherType = HYBRID_DITHER;
  259.       } else if (strcmp(argv[mark], "hybrid2") == 0) {
  260.     argc--; mark++;
  261.     ditherType = HYBRID2_DITHER;
  262.       } else if (strcmp(argv[mark], "fs4") == 0) {
  263.     argc--; mark++;
  264.     ditherType = FS4_DITHER;
  265.       } else if (strcmp(argv[mark], "fs2") == 0) {
  266.     argc--; mark++;
  267.     ditherType = FS2_DITHER;
  268.       } else if (strcmp(argv[mark], "fs2fast") == 0) {
  269.     argc--; mark++;
  270.     ditherType = FS2FAST_DITHER;
  271.       } else if (strcmp(argv[mark], "hybrid2") == 0) {
  272.     argc--; mark++;
  273.     ditherType = HYBRID2_DITHER;
  274.       } else if (strcmp(argv[mark], "2x2") == 0) {
  275.     argc--; mark++;
  276.     ditherType = Twox2_DITHER;
  277.       } else if (strcmp(argv[mark], "gray") == 0) {
  278.     argc--; mark++;
  279.     ditherType = GRAY_DITHER;
  280.       } else if (strcmp(argv[mark], "color") == 0) {
  281.     argc--; mark++;
  282.     ditherType = FULL_COLOR_DITHER;
  283.       } else if (strcmp(argv[mark], "none") == 0) {
  284.     argc--; mark++;
  285.     ditherType = NO_DITHER;
  286.       } else if (strcmp(argv[mark], "ordered") == 0) {
  287.     argc--; mark++;
  288.     ditherType = ORDERED_DITHER;
  289.       } else if (strcmp(argv[mark], "ordered2") == 0) {
  290.     argc--; mark++;
  291.     ditherType = ORDERED2_DITHER;
  292.       } else if (strcmp(argv[mark], "mbordered") == 0) {
  293.     argc--; mark++;
  294.     ditherType = MBORDERED_DITHER;
  295.       } else if (strcmp(argv[mark], "mono") == 0) {
  296.     argc--; mark++;
  297.     ditherType = MONO_DITHER;
  298.       } else if (strcmp(argv[mark], "threshold") == 0) {
  299.     argc--; mark++;
  300.     ditherType = MONO_THRESHOLD;
  301.       } else {
  302.     perror("Illegal dither option.");
  303.     usage(argv[0]);
  304.       }
  305.     } 
  306.     else if (strcmp(argv[mark], "-eachstat") == 0) {
  307.       argc--; mark++;
  308. #ifdef ANALYSIS
  309.       showEachFlag = 1;
  310. #else
  311.       fprintf(stderr, "To use -eachstat, recompile with -DANALYSIS in CFLAGS\n");
  312.       exit(1);
  313. #endif
  314.     }
  315.     else if (strcmp(argv[mark], "-shmem_off") == 0) {
  316.       argc--; mark++;
  317.       shmemFlag = 0;
  318.     }
  319.     else if (strcmp(argv[mark], "-quiet") == 0) {
  320.       argc--; mark++;
  321.       quietFlag = 1;
  322.     }
  323.     else if (strcmp(argv[mark], "-loop") == 0) {
  324.       argc--; mark++;
  325.       loopFlag = 1;
  326.     }
  327.     else if (strcmp(argv[mark], "-no_display") == 0) {
  328.       argc--; mark++;
  329.       noDisplayFlag = 1;
  330.     }
  331.     else if (strcmp(argv[mark], "-l_range") == 0) {
  332.       argc--; mark++;
  333.       LUM_RANGE = atoi(argv[mark]);
  334.       if (LUM_RANGE < 1) {
  335.     fprintf(stderr, "Illegal luminance range value: %d\n", LUM_RANGE);
  336.     exit(1);
  337.       }
  338.       argc--; mark++;
  339.     }
  340.     else if (strcmp(argv[mark], "-cr_range") == 0) {
  341.       argc--; mark++;
  342.       CR_RANGE = atoi(argv[mark]);
  343.       if (CR_RANGE < 1) {
  344.     fprintf(stderr, "Illegal cr range value: %d\n", CR_RANGE);
  345.     exit(1);
  346.       }
  347.       argc--; mark++;
  348.     }
  349.     else if (strcmp(argv[mark], "-cb_range") == 0) {
  350.       argc--; mark++;
  351.       CB_RANGE = atoi(argv[mark]);
  352.       if (CB_RANGE < 1) {
  353.     fprintf(stderr, "Illegal cb range value: %d\n", CB_RANGE);
  354.     exit(1);
  355.       }
  356.       argc--; mark++;
  357.     }
  358.     else if (argv[mark][0] == '-') {
  359.       fprintf(stderr, "Un-recognized flag %s\n",argv[mark]);
  360.       usage(argv[0]);
  361.     }
  362.     else {
  363.       input = fopen(argv[mark], "r");
  364.       if (input == NULL) {
  365.     fprintf(stderr, "Could not open file %s\n", argv[mark]);
  366.     usage(argv[0]);
  367.       }
  368.       argc--; mark++;
  369.     }
  370.   }
  371.  
  372.   lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
  373.   cr_values = (int *) malloc(CR_RANGE*sizeof(int));
  374.   cb_values = (int *) malloc(CB_RANGE*sizeof(int));
  375.  
  376.   signal(SIGINT, int_handler);
  377.  
  378.   init_tables();
  379.   
  380.   switch (ditherType) {
  381.     
  382.   case HYBRID_DITHER:
  383.     
  384.     InitColor();
  385.     InitHybridDither();
  386.     InitDisplay(name);
  387.     break;
  388.     
  389.     case HYBRID2_DITHER:
  390.     InitColor();
  391.     InitHybridErrorDither();
  392.     InitDisplay(name);
  393.     break;
  394.     
  395.   case FS4_DITHER:
  396.     InitColor();
  397.     InitFS4Dither();
  398.       InitDisplay(name);
  399.     break;
  400.     
  401.   case FS2_DITHER:
  402.     InitColor();
  403.     InitFS2Dither();
  404.     InitDisplay(name);
  405.     break;
  406.     
  407.   case FS2FAST_DITHER:
  408.     InitColor();
  409.     InitFS2FastDither();
  410.     InitDisplay(name);
  411.     break;
  412.     
  413.   case Twox2_DITHER:
  414.     InitColor();
  415.     Init2x2Dither();
  416.     InitDisplay(name);
  417.     PostInit2x2Dither();
  418.     break;
  419.  
  420.   case GRAY_DITHER:
  421.     InitGrayDisplay(name);
  422.     break;
  423.  
  424.   case FULL_COLOR_DITHER:
  425.     InitColorDither();
  426.     InitColorDisplay(name);
  427.     break;
  428.  
  429.   case NO_DITHER:
  430.     shmemFlag = 0;
  431.     break;
  432.  
  433.   case ORDERED_DITHER:
  434.     InitColor();
  435.     InitOrderedDither();
  436.     InitDisplay(name);
  437.     break;
  438.  
  439.   case MONO_DITHER:
  440.   case MONO_THRESHOLD:
  441.     InitMonoDisplay(name);
  442.     break;
  443.  
  444.   case ORDERED2_DITHER:
  445.     InitColor();
  446.     InitDisplay(name);
  447.     InitOrdered2Dither();
  448.     break;
  449.  
  450.   case MBORDERED_DITHER:
  451.     InitColor();
  452.     InitDisplay(name);
  453.     InitMBOrderedDither();
  454.     break;
  455.  
  456.   }
  457.  
  458. #ifdef SH_MEM
  459.     if (shmemFlag && (display != NULL)) {
  460.       if (!XShmQueryExtension(display)) {
  461.     shmemFlag = 0;
  462.     if (!quietFlag) {
  463.       fprintf(stderr, "Shared memory not supported\n");
  464.       fprintf(stderr, "Reverting to normal Xlib.\n");
  465.     }
  466.       }
  467.     }
  468. #endif
  469.  
  470.   if (setjmp(env) != 0) {
  471.  
  472.     DestroyVidStream(theStream);
  473.  
  474.     rewind(input);
  475.  
  476.     EOF_flag = 0;
  477.     curBits = 0;
  478.     bitOffset = 0;
  479.     bufLength = 0;
  480.     bitBuffer = NULL;
  481.     totNumFrames = 0;
  482. #ifdef ANALYSIS 
  483.     init_stats();
  484. #endif
  485.  
  486.   }
  487.  
  488.   theStream = NewVidStream(BUF_LENGTH);
  489.  
  490.  
  491.   mpegVidRsrc(0, theStream);
  492.  
  493.   if (ditherType == Twox2_DITHER) i = 2;
  494.   else i = 1;  
  495.  
  496.   ResizeDisplay(curVidStream->h_size*i, curVidStream->v_size*i);
  497.  
  498.   realTimeStart = ReadSysClock();
  499.  
  500.   while (1) mpegVidRsrc(0, theStream);
  501. }
  502.  
  503.  
  504. /*
  505.  *--------------------------------------------------------------
  506.  *
  507.  * usage --
  508.  *
  509.  *    Print mpeg_play usage
  510.  *
  511.  * Results:
  512.  *    None.
  513.  *
  514.  * Side effects:
  515.  *    exits with a return value -1
  516.  *
  517.  *--------------------------------------------------------------
  518.  */
  519.  
  520. void
  521. usage(s)
  522. char *s;    /* program name */
  523. {
  524.     fprintf(stderr, "Usage:\n");
  525.     fprintf(stderr, "mpeg_play\n");
  526.     fprintf(stderr, "          [-nob]\n");
  527.     fprintf(stderr, "          [-nop]\n");
  528.     fprintf(stderr, "          [-dither {ordered|ordered2|mbordered|fs4|fs2|fs2fast|hybrid|\n");
  529.     fprintf(stderr, "                    hybrid2|2x2|gray|color|none|mono|threshold}]\n");
  530.     fprintf(stderr, "          [-loop]\n");
  531.     fprintf(stderr, "          [-eachstat]\n");
  532.     fprintf(stderr, "          [-no_display]\n");
  533.     fprintf(stderr, "          [-quiet]\n");
  534.     fprintf(stderr, "          file_name\n");
  535.     exit (-1);
  536. }
  537.  
  538.  
  539.  
  540. /*
  541.  *--------------------------------------------------------------
  542.  *
  543.  * DoDitherImage --
  544.  *
  545.  *    Called when image needs to be dithered. Selects correct
  546.  *      dither routine based on info in ditherType.
  547.  *
  548.  * Results:
  549.  *    None.
  550.  *
  551.  * Side effects:
  552.  *    None.
  553.  *
  554.  *--------------------------------------------------------------
  555.  */
  556.  
  557. void
  558. DoDitherImage(l, Cr, Cb, disp, h, w) 
  559. unsigned char *l, *Cr, *Cb, *disp;
  560. int h,w;
  561. {
  562.  
  563.   switch(ditherType) {
  564.   case HYBRID_DITHER:
  565.     HybridDitherImage(l, Cr, Cb, disp, h, w);
  566.     break;
  567.  
  568.   case HYBRID2_DITHER:
  569.     HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
  570.     break;
  571.  
  572.   case FS2FAST_DITHER:
  573.     FS2FastDitherImage(l, Cr, Cb, disp, h, w);
  574.     break;
  575.  
  576.   case FS2_DITHER:
  577.     FS2DitherImage(l, Cr, Cb, disp, h, w);
  578.     break;
  579.  
  580.   case FS4_DITHER:
  581.     FS4DitherImage(l, Cr, Cb, disp, h, w);
  582.     break;
  583.  
  584.   case Twox2_DITHER:
  585.     Twox2DitherImage(l, Cr, Cb, disp, h, w);
  586.     break;
  587.  
  588.   case FULL_COLOR_DITHER:
  589.     ColorDitherImage(l, Cr, Cb, disp, h, w);
  590.     break;
  591.  
  592.   case GRAY_DITHER:
  593.     GrayDitherImage(l, Cr, Cb, disp, h, w);
  594.     break;
  595.  
  596.   case NO_DITHER:
  597.     break;
  598.  
  599.   case ORDERED_DITHER:
  600.     OrderedDitherImage(l, Cr, Cb, disp, h, w);
  601.     break;
  602.  
  603.   case MONO_DITHER:
  604.     MonoDitherImage(l, Cr, Cb, disp, h, w);
  605.     break;
  606.  
  607.   case MONO_THRESHOLD:
  608.     MonoThresholdImage(l, Cr, Cb, disp, h, w);
  609.     break;
  610.  
  611.   case ORDERED2_DITHER:
  612.     Ordered2DitherImage(l, Cr, Cb, disp, h, w);
  613.     break;
  614.  
  615.   case MBORDERED_DITHER:
  616.     MBOrderedDitherImage(l, Cr, Cb, disp, h, w);
  617.     break;
  618.   }
  619. }
  620.